﻿import MySecurity.*;

/**
* ¼ӽâÃÜÀà
*/
class MySecurity.RSA{
	public var e:BigInt;
	public var d:BigInt;
	public var m:BigInt;
	public var chunkSize:Number;
	public var radix:Number;
	public var barrett:Barrett;
	
	public function RSA(encryptionExponent:String, decryptionExponent:String, modulus:String){
		this.e = BigInt.biFromHex(encryptionExponent);
		this.d = BigInt.biFromHex(decryptionExponent);
		this.m = BigInt.biFromHex(modulus);
		this.chunkSize = 2 * BigInt.biHighIndex(this.m);
		this.radix = 16;
		this.barrett = new Barrett(this.m);
	}
	
	/**
	* ¼ÓÃÜ×ִ®
	* @param	key RSAÀàÐÍ
	* @param	s Ҫ¼ÓÃܵÄ×ִ®
	* @return	¼ÓÃܺóµÄ×ִ®
	*/
	public static function encryptedString(key:RSA, s:String):String
	{
		var a:Array = new Array();
		var sl:Number = s.length;
		var i:Number = 0;
		while (i < sl) {
			a[i] = s.charCodeAt(i);
			i++;
		}

		while (a.length % key.chunkSize != 0) {
			a[i++] = 0;
		}

		var al:Number = a.length;
		var result:String = "";
		var j:Number, k:Number, block:BigInt;
		var i:Number=0;
		while(i< al){
			block = new BigInt();
			j = 0;
			var k=i;
			trace("==============")
			var strs="";
			while(k < i + key.chunkSize){
				strs+=s.charAt(k);
				block.digits[j] = a[k++];
				strs+=s.charAt(k);
				block.digits[j] += a[k++] << 8;
				j++;
				
			}
			trace(strs);
			trace("---------------\r");
			var crypt = key.barrett.powMod(block, key.e);
			trace("::::::::::::::"+crypt);
			var text = key.radix == 16 ? BigInt.biToHex(crypt) : BigInt.biToString(crypt, key.radix);
			result += text + " ";
			i += key.chunkSize;
		}
		return result.substring(0, result.length - 1); 
	}
	/**
	* ½âÃܺ¯Êý
	* @param	key ½âÃÜÓõÄRSA
	* @param	s Ҫ½âÃܵÄ×ִ®
	* @return	½âÃܺóµÄ×ִ®
	*/
	public static function decryptedString(key:RSA, s:String):String
	{
		var blocks:Array = s.split(" ");
		var result:String = "";
		var i:Number, j:Number, block:BigInt;
		for (i = 0; i < blocks.length; ++i) {
			var bi;
			if (key.radix == 16) {
				bi = BigInt.biFromHex(blocks[i]);
			}
			else {
				bi = BigInt.biFromString(blocks[i], key.radix);
			}
			block = key.barrett.powMod(bi, key.d);
			for (j = 0; j <= BigInt.biHighIndex(block); ++j) {
				result += String.fromCharCode(block.digits[j] & 255, block.digits[j] >> 8);
			}
		}
		// Remove trailing null, if any.
		if (result.charCodeAt(result.length - 1) == 0) {
			result = result.substring(0, result.length - 1);
		}
		return result;
	}
	
}